﻿
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Nacos.V2;
using Nacos;

namespace NacosApp.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController
    {
        private readonly INacosConfigService _svc;
        private readonly INacosNamingService _namesvc;
        private readonly IHttpClientFactory _factory;

        public ValuesController(INacosConfigService svc, INacosNamingService namesvc, IHttpClientFactory factory)
        {
            _svc = svc;
            _namesvc = namesvc;
            _factory = factory;
        }
        [HttpGet("Get")]
        public async Task<string> Get([FromQuery] string key)
        {
            var group = "demo-group";
            var res = await _svc.GetConfig(key, group, 5000L);
            return string.IsNullOrWhiteSpace(res) ? "Not Found" : res;
        }
        [HttpGet("publish")]
        public async Task<string> PublishConfig([FromQuery] string key)
        {
            var group = "demo-group";
            var val = "test-value-" + DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
            await Task.Delay(500);
            var res = await _svc.PublishConfig(key, group, val);
            return !res ? "Not Found" : "发布配置结果："+val;
        }
        [HttpGet("remove")]
        public async Task<string> RemoveConfig([FromQuery] string key)
        {
            var group = "demo-group";
            await Task.Delay(500);
            var flag = await _svc.RemoveConfig(key, group);
            return !flag ? "Not Found" : "删除配置";
        }
        [HttpGet("test1")]
        public async Task<String> Test1([FromQuery] string key)
        {
            // need to know the service name.
            await Task.Delay(500);

            var instace = new Nacos.V2.Naming.Dtos.Instance
            {
                ServiceName = key,
                Ip = "127.0.0.1",
                Port = 44376,
                Enabled = false,
                Healthy = false,
                Ephemeral = false,
                Weight = 100,
                InstanceId = $"demo-svc1-127.0.0.1-{44376}",
                Metadata = new System.Collections.Generic.Dictionary<string, string>
                {
                    { "m1", "v1" },
                    { "m2", "v2" },
                }
            };

            // 注册实例有很多重载，选适合自己的即可。
            await _namesvc.RegisterInstance(key, "127.0.0.1", 44376);
            Console.WriteLine($"==========={key}===========注册实例成功");
            return "注册实例成功";
        }
        [HttpGet("test2")]
        public async Task<String> Test2([FromQuery] string key)
        {
            // need to know the service name.
            await Task.Delay(500);


            // 获取全部实例有很多重载，选适合自己的即可。最后一个参数表明要不要订阅这个服务
            // SelectInstances, SelectOneHealthyInstance 是另外的方法可以获取服务信息。
            var list = await _namesvc.GetAllInstances(key, Nacos.V2.Common.Constants.DEFAULT_GROUP, false);
            return "获取实例成功 :"+ Newtonsoft.Json.JsonConvert.SerializeObject(list);
        }
        [HttpGet("test3")]
        public async Task<String> Test3([FromQuery] string key)
        {
            // need to know the service name.
            await Task.Delay(500);

            // 注销实例有很多重载，选适合自己的即可。
            await _namesvc.DeregisterInstance(key, Nacos.V2.Common.Constants.DEFAULT_GROUP, "127.0.0.1", 44376);
            return "======================注销实例成功";
        }


        // GET /
        [HttpGet("getRandom")]
        public ActionResult<IEnumerable<string>> Get()
        {
            var nx = new Random().Next(1,99999);
            return new string[] { "value1", "value2", nx.ToString() };
        }

        // GET /a
        [HttpGet("tryGet")]
        public async Task<string> tryGetAsync(string key)
        {
            // 找出一个健康的实例
            var instance = await _namesvc.SelectOneHealthyInstance(key, "DEFAULT_GROUP");
            var host = $"{instance.Ip}:{instance.Port}";

            // 根据 secure 来判断服务要不要用 https，
            // 这里是约定，参考了 spring cloud 那边，不是强制的，也可以用其他标识
            var baseUrl = instance.Metadata.TryGetValue("secure", out _)
                ? $"https://{host}"
                : $"http://{host}";

            if (string.IsNullOrWhiteSpace(baseUrl))
            {
                return "empty";
            }

            var url = $"{baseUrl}";

            var client = _factory.CreateClient();

            var resp = await client.GetAsync(url+ @"/api/values/getRandom");
            var returnValue = await resp.Content.ReadAsStringAsync();
            return url + ":" + returnValue;
        }

        static async Task Subscribe(INacosNamingService svc, IEventListener listener)
        {
            // 订阅服务变化
            await svc.Subscribe("demo-svc1", Nacos.V2.Common.Constants.DEFAULT_GROUP, listener);

            // 模拟服务变化，listener会收到变更信息
            await RegisterInstance(svc, 9997);

            await Task.Delay(3000);

            // 取消订阅
            await svc.Unsubscribe("demo-svc1", Nacos.V2.Common.Constants.DEFAULT_GROUP, listener);

            // 服务变化后，listener不会收到变更信息
            await RegisterInstance(svc);

            await Task.Delay(1000);
        }
        static async Task RegisterInstance(INacosNamingService svc, int port = 9999)
        {
            await Task.Delay(500);

            var instace = new Nacos.V2.Naming.Dtos.Instance
            {
                ServiceName = "demo-svc1",
                ClusterName = Nacos.V2.Common.Constants.DEFAULT_CLUSTER_NAME,
                Ip = "127.0.0.1",
                Port = port,
                Enabled = true,
                Ephemeral = true,
                Healthy = true,
                Weight = 100,
                InstanceId = $"demo-svc1-127.0.0.1-{port}",
                Metadata = new System.Collections.Generic.Dictionary<string, string>
        {
            { "m1", "v1" },
            { "m2", "v2" },
        }
            };

            // 注册实例有很多重载，选适合自己的即可。
            await svc.RegisterInstance(instace.ServiceName, Nacos.V2.Common.Constants.DEFAULT_GROUP, instace);
            Console.WriteLine($"======================注册实例成功");
        }

        static async Task GetAllInstances(INacosNamingService svc)
        {
            await Task.Delay(500);

            // 获取全部实例有很多重载，选适合自己的即可。最后一个参数表明要不要订阅这个服务
            // SelectInstances, SelectOneHealthyInstance 是另外的方法可以获取服务信息。
            var list = await svc.GetAllInstances("demo-svc1", Nacos.V2.Common.Constants.DEFAULT_GROUP, false);
            Console.WriteLine($"======================获取实例成功，{Newtonsoft.Json.JsonConvert.SerializeObject(list)}");
        }

        static async Task DeregisterInstance(INacosNamingService svc)
        {
            await Task.Delay(500);

            // 注销实例有很多重载，选适合自己的即可。
            await svc.DeregisterInstance("demo-svc1", Nacos.V2.Common.Constants.DEFAULT_GROUP, "127.0.0.1", 8848);
            Console.WriteLine($"======================注销实例成功");
        }
    }
}
